mmt - denken in knopen
Home

mmt - denken in knopen

mmt - denken in knopen

Knopen of knooppunten zijn objecten die op hun beurt weer objecten zijn. Hiërachische- of boomstructuren. Geneste objecten of objecten van objecten. Je moet echt leren denken in objecten (JS - werken met objecten).

Knopen

Vooraleer we met React begonnen, hebben we een webpagina bekeken vanuit het standpunt van een HTML document. Een platte tekst met daarin HTML element.

Als we de webpagina interactief willen maken hebben we geleerd dat de DOM het document als knooppunten van objecten voorstelt. Op die manier kunnen we de platte HTML tekst bewerken met behulp van JavaScript. De DOM is een objectgeoriënteerde weergave van de webpagina, die kan worden gewijzigd met een scripttaal zoals JavaScript.

Als we met React werken is het vertrekpunt niet meer het HTML document maar de DOM voorstelling van de HTML elementen, dwz knopen van objecten die op hun beurt weer objecten zijn. React creëert een virtuele DOM en rendert die in de browser.

Als we webpagina's ontwikkelen met React moeten we van invalshoek veranderen. Niet meer denken in HTML elementen maar in HTML objecten en knooppunten.

We ontwikkelen een webapplicatie waarmee je artikelen kan aanbieden aan de gebruiker. Dat kunnen om het even welke artikelen zijn, van fietsen, petten tot boeken. Als voorbeeld ontwikkelen we een reisapplicatie. De website heeft een overzicht van alle dolmens en menhirs in de Sarthe in Frankrijk.

  1. De ArticleSummary knoop
    Deze knoop bevat de samenvatting van het artikel.
    1. wireframe
      article-overview node
      article-overview node
    2. technische analyse
      1. De afbeelding en de knop staan onder elkaar. Het article element maken we dus flex en de richting stellen we in op column.
      2. De stijl voor de Article tag plaatsen we in de functie-component omdat we die alleen daar gaan gebruiken.
      3. We hergebruiken onze AButton functie-component.
      4. We maken een ui-article.js bestand om alle ui elementen in zetten die met het mmt project te maken te maken.
      5. We hergebruiken ui-controls.js maar schonen het op. We houden alleen die controls over die we gaan gebruiken. Ik heb de namen van style constanten wel hernoemd. buttonStyle en labelStyle zijn gewoon style geworden. Die constanten staat in een functie-component en kunnen dus dezelfde naam hebben.
      6. En we voegen er een ImageSummary control aan toe in de vorm van een functie-component. Deze component dient om een afbeelding in klein formaat te tonen:
    3. denken in knopen
      1. die wireframe bestaat uit twee knopen, een button knoop en een image knoop.
        1. Abutton knoop:
          We hebben al een Abutton functie-component gemaakt. We gaan die hergebruiken. We hernoemen alleen de buttonStyle constante naar style. We hoeven daar geen button aan toe te voegen omdat de style in een functie-component staat.
        2. ImageSummary knoop
          We maken een image knoop met de naam ImageSummary:
          function ImageSummary(props) {
              const style = {
                  borderRadius: "6px",
              }
              return (<img style={style} alt={`afbeelding van ${props.name}`} src={props.image} />
              );
          }
      2. De ArticleSummary knoop is samengesteld uit de 2 knopen van hierboven.
        1. code:
          function ArticleSummary(props) {
              const style = {
                  display: "flex",
                  flexDirection: "column",
                  width: "10em"
              }
              return (<article style={style}>
                  <ImageOverview name={props.name} image={props.image}/>
                  <AButton caption={props.name}/>
              </article>);
          }
        2. renderen in index.html:
          <body>
              <div id="root"></div>
              <script type="text/babel">
                  ReactDOM.render(<ArticleSummary name="Allée couverte du Colombier" image="images/small/Allee couverte du Colombier.jpg" />,
                      document.querySelector('#root'))
              </script>
          </body>
        3. resultaat:
          resultaat ArticleSummary function-component
          resultaat ArticleSummary function-component
  2. Een ArticleOverview knoop
    1. wireframe
      mmt-index-pagina-excursion
      mmt-index-pagina-excursion
    2. denken in knopen
      1. ArticleHeader
        1. Let erop hoe we een styled component maken. De CSS stijl bestaat uit een style object van drie objecten, een header, een title en een logo subobject. Er zijn vier mogelijkheden om CSS toe te passen op componenten. We gebruiken hier Inline styling.In React worden inline stijlen niet gespecificeerd als een string. In plaats daarvan worden ze gedefinieerd als een object waarvan de sleutels de camelCased-versie van de CSS-stijleigenschap is en waarvan de waarde de waarde van de stijl is, meestal een tekenreeks.
        2. We gaan die component op elke pagina van de website gebruiken.
        3. code:
          function ArticleHeader(props) {
              const style = {
                  header: {
                      display: "flex",
                      flexDirection: "row",
                      justifyContent: "space-between",
                      width: "100%",
                      heigth: "10em"
                  },
                  title: {
                      alignSelf: "center",
                      fontFamily: "Arial",
                      color: "red",
                      paddingRight: "1em"
                  },
                  logo: {
                      height: "10em"
                  }
              }
              return (<header style={style.header}>
                  <img alt={`Logo ${props.title}`} src={props.image} style={style.logo}/>
                  <h1 style={style.title}>{props.title}</h1>
              </header>);
          }
          
        4. uitproberen in index.html:
          <body>
              <div id="root"></div>
              <script type="text/babel">        
                  ReactDOM.render(<ArticleHeader title="Moe maar tevreden" image="images/mmt-logo.png" />,
                      document.querySelector('#root'))
              </script>
          </body>
          
        5. Resultaat:
          resultaat ArticleHeader function-component
          resultaat ArticleHeader function-component
        6. We halen de lijst van de bezienswaardigheden uit het JSON bestand in te lezen. Zie hiervoor: JSON - bestand inlezen met Fetch API. We doen dat in index.html. Eerst proberen we het JSON bestand in te lezen en als het lukt renderen we de ArticleHeader component. De titel en de url voor het logo halen we uit het JSON object:
          <body>
              <div id="root"></div>
              <script type="text/babel">
                  const url = 'data/neolithicum.json';
                  const myRequest = new Request(url);
                  fetch(myRequest)
                      .then(response => response.json())
                      .then(data => {
                          ReactDOM.render(<ArticleHeader title={data.title} image={data.logoUrl} />,
                              document.querySelector('#root'));
                      })
                      .catch(response => alert("Kan JSON bestand niet openen."));
              </script>
          </body>
          
        7. Resultaat:
          Nu staat de titel uit het JSON bestand erin:
          resultaat ArticleHeader function-component props JSON
          resultaat ArticleHeader function-component props JSON
      2. Een ArticleOverview knoop
        1. Een lijst van ArticleSummary componenten. Voor elk item van de het cusiosity array van objecten maken we een ArticleSummary component:
          function ArticleOverview(props) {
              const style = {
                  color: 'white',
                  display: 'flex',
                  flexWrap: 'wrap'
              };
              // alert(JSON.stringify(props));
              return (
                  <main>
                      <div style={style}>
                          {props.article.map(item => (<ArticleSummary item={item} key={item.key} action={props.action} />))}
                      </div>
                  </main>
              );
          }
  3. Een ArticleDetail knoop
    1. wireframe
      article-detail node
      article-detail node
    2. denken in knopen
    3. de wireframe kunnen we opdelen in verschillende knopen:
      1. een ongeordende lijst met de tekstbeschrijving
      2. een afbeelding
      3. een kaart
      4. een label voor de titel
      5. een LikePanel
      6. een tekstveld en Submit knop
      7. een lijst met de commentaren
      8. een knop om terug te keren naar het overzicht
    4. code:
      class ArticleDetail extends React.Component {
          style = {
              detail: {
                  display: "flex",
                  flexDirection: "column",
                  width: "70%"
              },
              top: {
                  display: "flex",
                  flexDirection: "row"
              },
              middle: {
                  display: "flex",
                  flexDirection: "row"
              },
              comment: {
                  display: "block"
              }
          }
      
          constructor(props) {
              super(props);
          }
      
          componentDidMount() {
              this.leafLetView('leaflet-id');
          }
      
          showOverview = () => { this.props.actionOverview() }
      
          leafLetView = (id) => {
              // Initialiseert de mijnKaart constante
              const map = L.map(id);
              // Laad de basiskaart
              const baseMap = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                  maxZoom: 19,
                  attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
              });
              // plaats de basismap in het html element met id = kaart-id
              baseMap.addTo(map);
              // Stel het gebied van de kaart in
              // de laatste parameter bepaalt de grootte van het getoonde gebied
              // hoe groter het getal, hoe gedetailleerder
              // alert(this.props.article.longitude);
              const pos1 = this.props.article.longitude.substr(0, 5);
              const pos2 = this.props.article.latitude.substr(0, 5);
              const mark = L.marker([this.props.article.latitude, this.props.article.longitude]).addTo(map);
              // alert(pos1 + pos2);
              map.setView([pos2, pos1], 12);
          }
      
          render() {
              return (<article style={this.style}>
                  <AButton caption="Terug naar overzicht" onClick={this.showOverview} />
                  <div style={this.style.top}>
                      <ImageDetail name={this.props.article.name} image={`images/big/${this.props.article.image}`} />
                      <LeafLetNode />
                  </div>
                  <div style={this.style.middle}>
                      <div>
                          <ul>
                              <li>{this.props.article.name}</li>
                              <li>{this.props.article.type}</li>
                              <li>{this.props.article.period}</li>
                              <li>{this.props.article.country}</li>
                              <li>{this.props.article.region}</li>
                              <li>{this.props.article.city}</li>
                          </ul>
                      </div>
                      <div>
                          <ul>
                              <li>{this.props.article.coordinates}</li>
                              <li>{this.props.article.longitude}</li>
                              <li>{this.props.article.latitude}</li>
                          </ul>
                          <LikePanel />
                      </div>
                  </div>
                  <textarea style={this.style.comment}></textarea>
                  <AButton caption="Verzenden" />
              </article>);
          }
      }
  4. ArticleApp
    1. Technische beschrijving
      De eigenlijk app knoop die ook dienst doet als controller. Daar houden we de state bij. Hiermee weten we als we de pagina opnieuw moeten renderen. In het geval de gebruiker op één artikel heeft geklikt of terug naar het overzicht wilt.
    2. Code:
      class ArticleApp extends React.Component {
          constructor(props) {
              super(props);
              this.state = {
                  overview: true
              };
          }
      
          showDetail = (item) => {
              this.setState({
                  overview: false,
                  article: item
              });
          };
      
          showOverview = () => {
              this.setState({
                  overview: true,
                  article: null
              });
          };
      
          render() {
              if (this.state.overview) {
                  return (
                      <ArticleOverview article={this.props.article} action={this.showDetail} />
                  );
              } else {
                  return (<ArticleDetail article={this.state.article} actionOverview={this.showOverview} />)
              }
          }
      }
    3. Tenslotte de index.html pagina:
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
          <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
          <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
          <script type="text/babel" src="js/ui-controls.js"></script>
          <script type="text/babel" src="js/ui-article.js"></script>
          <link crossorigin="" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
              integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
              rel="stylesheet" />
          <script crossorigin=""
              integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
              src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
          <title>Moe maar tevreden</title>
      </head>
      <body>
          <header id="header"></header>
          <div id="root"></div>
          <script type="text/babel">
              const url = 'data/neolithicum.json';
              const myRequest = new Request(url);
              fetch(myRequest)
                  .then(response => response.json())
                  .then(data => {
                      ReactDOM.render(<ArticleHeader title={data.title} image={data.logoUrl} />,
                          document.querySelector('#header'));
                          ReactDOM.render(<ArticleApp article={data.curiosity} />,
                          document.querySelector('#root'));
                  })
                  .catch(response => alert(response));
          </script>
      </body>
      </html>

JI
2020-05-03 18:58:14